import axios, {AxiosInstance, AxiosRequestConfig, AxiosResponse} from 'axios';

//目的:
//1. 增加一些默认的配置和拦截器
//2. 限制用户传递的类型: 返回值的类型

//一般后端返回的类型都是固定的
/*
{
  code:
  data:
  msg:
}*/

export interface ResponseData<T> {
  code: number;
  data?: T;
  msg?: string;
}

class HttpRequest {
  public baseURL = 'http://localhost:3000/api'
  public timeout = 3000;

  public request(options: AxiosRequestConfig){
    const instance = axios.create();
    //↑ 方便我们后面取消, 不然同一个实例, 一取消就都取消了

    options = this.mergeOptions(options); // 合并后的选项
    this.setInterceptors(instance);

    return instance(options);
  }

  public setInterceptors(instance: AxiosInstance){
    instance.interceptors.request.use((config) => {
      config.headers!['token'] = 'xxx';
      return config;
    }, (err) => {
      return Promise.reject(err);
    });

    instance.interceptors.response.use((res) => {
      let {data: {code}} = res.data;
      if(code !== 0){
        return Promise.reject(res);
      }
      return res;

    }, (err) => {
      return Promise.reject(err);
    });
  }

  mergeOptions(options: AxiosRequestConfig){
    return Object.assign({baseURL: this.baseURL, timeout: this.timeout}, options);
  }

  public async get<T = any>(url: string, data: any): Promise<ResponseData<T>/*← 装包*/>{
    return this.request({
      method: 'get',
      url,
      params: data
    })
      .then(res => {
        return Promise.resolve(res.data);
      })
      .catch(err => {
        return Promise.reject(err);
      });
  }

  public async post<T = any>(url: string, data: any): Promise<ResponseData<T>/*← 装包*/>{
    return this.request({
      method: 'post',
      url,
      data
    })
      .then(res => {
        return Promise.resolve(res.data);
      })
      .catch(err => {
        return Promise.reject(err);
      });
  }
}

const http = new HttpRequest();
http.get<{ token: number;}>('/login', {username: 'ahhh', password: '123'})
  .then(res => {
    res.data?.token
  });

export {};
